package com.hospital.wx.util;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.*;

@Component
public class AliyunOSSUtil {

    // 从配置文件注入参数
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;

    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId;

    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;

    @Value("${aliyun.oss.bucketName}")
    private String bucketName;

    // 获取OSS客户端实例
    private OSS getOSSClient() {
        return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    }

    /**
     * 上传文件到OSS（公共读权限桶适配版）
     * @param inputStream 文件输入流
     * @param fileName 文件名（包含路径，如"images/pic1.jpg"）
     * @return 上传成功返回文件的公开URL，失败返回null
     */
    public String uploadFile(InputStream inputStream, String fileName) {
        OSS ossClient = null;
        try {
            ossClient = getOSSClient();

            // 检查Bucket是否存在，不存在则创建
            if (!ossClient.doesBucketExist(bucketName)) {
                ossClient.createBucket(bucketName);
                // 设置Bucket的访问权限为公共读
                ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
            }

            // 上传文件时设置HTTP头，支持浏览器预览
            ObjectMetadata metadata = new ObjectMetadata();
            // 设置内容处置为内联预览
            metadata.setContentDisposition("inline;filename=" + fileName);
            // 根据文件名自动推断Content-Type（如image/jpeg, image/png等）
            String contentType = getContentType(fileName);
            if (contentType != null) {
                metadata.setContentType(contentType);
            }

            // 上传文件
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, inputStream, metadata);
            ossClient.putObject(putObjectRequest);

            // 生成公共读权限下的固定URL（无需过期时间）
            // URL格式：https://bucketName.endpoint/fileName
            return String.format("https://%s.%s/%s", bucketName, endpoint, fileName);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            // 关闭OSS客户端
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 从文件名获取内容类型，用于设置Content-Type头
     */
    private String getContentType(String fileName) {
        String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        switch (fileExtension) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            case "bmp":
                return "image/bmp";
            case "webp":
                return "image/webp";
            default:
                return null; // 使用默认类型
        }
    }

    /**
     * 从OSS下载文件
     * @param fileName 文件名（包含路径）
     * @param localFilePath 本地保存路径
     * @return 下载成功返回true，失败返回false
     */
    public boolean downloadFile(String fileName, String localFilePath) {
        OSS ossClient = null;
        try {
            ossClient = getOSSClient();

            // 检查文件是否存在
            if (!ossClient.doesObjectExist(bucketName, fileName)) {
                System.out.println("文件不存在：" + fileName);
                return false;
            }

            // 下载文件
            File file = new File(localFilePath);
            // 确保父目录存在
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            ossClient.getObject(new GetObjectRequest(bucketName, fileName), file);
            return true;

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 删除OSS上的文件
     * @param fileName 文件名（包含路径）
     * @return 删除成功返回true，失败返回false
     */
    public boolean deleteFile(String fileName) {
        OSS ossClient = null;
        try {
            ossClient = getOSSClient();
            ossClient.deleteObject(bucketName, fileName);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 上传文件到OSS（支持不同文件类型路径）
     * @param inputStream 文件输入流
     * @param originalFileName 原始文件名
     * @param fileType 文件类型（qualification、service、avatar）
     * @param fileSize 文件大小（字节）
     * @return 上传结果，包含URL、文件名、大小等信息
     */
    public UploadResult uploadFileWithType(InputStream inputStream, String originalFileName, String fileType, long fileSize) {
        OSS ossClient = null;
        try {
            // 生成唯一的文件名
            String fileExtension = getFileExtension(originalFileName);
            String uniqueFileName = generateUniqueFileName(fileType, fileExtension);
            
            ossClient = getOSSClient();

            // 检查Bucket是否存在，不存在则创建
            if (!ossClient.doesBucketExist(bucketName)) {
                ossClient.createBucket(bucketName);
                // 设置Bucket的访问权限为公共读
                ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
            }

            // 上传文件时设置HTTP头，支持浏览器预览
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentDisposition("inline;filename=" + originalFileName);
            String contentType = getContentType(originalFileName);
            if (contentType != null) {
                metadata.setContentType(contentType);
            }

            // 上传文件
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, uniqueFileName, inputStream, metadata);
            PutObjectResult result = ossClient.putObject(putObjectRequest);

            // 生成公共读权限下的固定URL
            String fileUrl = String.format("https://%s.%s/%s", bucketName, endpoint, uniqueFileName);
            
            // 构建上传结果
            UploadResult uploadResult = new UploadResult();
            uploadResult.setUrl(fileUrl);
            uploadResult.setFilename(originalFileName);
            uploadResult.setSize(fileSize);
            uploadResult.setFileType(fileType);
            uploadResult.setUniqueFileName(uniqueFileName);
            
            return uploadResult;

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            // 关闭OSS客户端
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        if (fileName == null || !fileName.contains(".")) {
            return "";
        }
        return fileName.substring(fileName.lastIndexOf("."));
    }

    /**
     * 生成唯一的文件名
     */
    private String generateUniqueFileName(String fileType, String fileExtension) {
        long timestamp = System.currentTimeMillis();
        String uuid = java.util.UUID.randomUUID().toString().replace("-", "");
        return String.format("%s/%s_%s%s", fileType, timestamp, uuid, fileExtension);
    }

    /**
     * 文件上传结果类
     */
    public static class UploadResult {
        private String url;
        private String filename;
        private long size;
        private String fileType;
        private String uniqueFileName;

        // Getters and Setters
        public String getUrl() { return url; }
        public void setUrl(String url) { this.url = url; }
        
        public String getFilename() { return filename; }
        public void setFilename(String filename) { this.filename = filename; }
        
        public long getSize() { return size; }
        public void setSize(long size) { this.size = size; }
        
        public String getFileType() { return fileType; }
        public void setFileType(String fileType) { this.fileType = fileType; }
        
        public String getUniqueFileName() { return uniqueFileName; }
        public void setUniqueFileName(String uniqueFileName) { this.uniqueFileName = uniqueFileName; }
    }
}
